package main

import (
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"
)

func main() {
	/*

		//作业01
		s := []int{1, 2, 3, 3}
		fmt.Println(SetIntArr(s))

	*/
	//作业02_给定一个字符串，统计其中所有类型字符出现的频率
	getHW2("112233")
	/*
		//作业03_封装一个四则运算的计算器

		sss, errss := FourFun(0, 0, "/")
		if errss != nil {
			fmt.Println(errss)
		} else {
			fmt.Println(sss)
		}
		//作业04_封装一个函数，功能为体脂计算器
		ssss := GetBMI()
		if ssss.err == nil {
			fmt.Println(ssss.pro)
		}
	*/

	//作业05_封装一个函数，功能为交换两个1数字
	/*
		var a = 1
		var b = 2
		//swapbyint(a, b)
		swap(a, b)
		fmt.Println("a=", a)
		fmt.Println("b=", b)
		//作业06_实现一个订票系统
		//DingPaoStart()
	*/
}

//作业01_给定一个int数组，判断是否存在重复元素
func SetIntArr(intarr []int) bool {
	var isTrue = false
	for i := 0; i < len(intarr); i++ {
		for j := i + 1; j < len(intarr); j++ {
			if intarr[i] == intarr[j] {
				isTrue = true
			}
		}
	}
	return isTrue
}

//作业02_给定一个字符串，统计其中所有类型字符出现的次数
func getHW2(s string) {
	var arr = GetFrequency(s)
	var marr = GetContainsNum(s)
	fmt.Println("该字符串出现控制字符的次数为", arr[0])
	fmt.Println("该字符串出现数字字符的次数为", arr[1])
	fmt.Println("该字符串出现字母字符的次数为", arr[2])
	fmt.Println("该字符串出现其他字符的次数为", arr[3])
	for key, val := range marr {
		fmt.Println(string(key), ":", val)
	}
}

func GetFrequency(s string) []int {
	var arr = make([]int, 4)
	sarr := []byte(s)
	for i := 0; i < len(sarr); i++ {
		switch {
		case 0 <= sarr[i] && sarr[i] <= 32:
			arr[0]++
		case 48 <= sarr[i] && sarr[i] <= 57:
			arr[1]++
		case 65 <= sarr[i] && sarr[i] <= 90:
			arr[2]++
		case 97 <= sarr[i] && sarr[i] <= 122:
			arr[2]++
		case sarr[i] == 127:
			arr[0]++
		default:
			fmt.Println(sarr[i])
			arr[3]++
		}
	}

	return arr
}

//获取每个的出现次数(map)
func GetContainsNum(s string) map[rune]int {
	var arr = []rune(s)
	var maps = make(map[rune]int)
	for i := 0; i < len(arr); i++ {
		maps[arr[i]]++
	}
	return maps
}

//作业03_封装一个四则运算的计算器
func FourFun(a interface{}, b interface{}, str string) (float64, error) {
	var res float64
	var err error
	af := SetType(a)
	bf := SetType(b)
	switch str {
	case "+":
		res = af + bf
		break
	case "-":
		res = af - bf
		break
	case "*":
		res = af * bf
		break
	case "/":
		if af != 0 {
			res = af / bf
		} else {
			err = errors.New("除数不能为空")
		}
		break
	}
	return res, err
}

//对参数格式进行校验
func SetType(inter interface{}) float64 {
	var res float64
	switch inter.(type) {
	case string:
		strconv.ParseFloat(inter.(string), 64)
		break
	case int:
		res = float64(inter.(int))
		break
	case float64:
		res = inter.(float64)
		break
	}
	return res
}

//定义个人信息结构体
type Boody struct {
	h   float64
	w   float64
	age float64
	sex float64
	BMI float64
	BFR float64
	pro string
	err error
}

//作业04_封装一个函数，功能为体脂计算器
func GetBMI() Boody {
	fmt.Println("     ,---,.                                                               ___                                    ,--,                             ,--,                  ___")
	fmt.Println("    ,'  .'  \\                ,---,                    .--.,              ,--.'|_                                ,--.'|                           ,--.'|                ,--.'|_")
	fmt.Println("  ,---.' .' |   ,---.      ,---.'|                  ,--.'  \\             |  | :,'                               |  | :                      ,--, |  | :                |  | :,'   ,---.    __  ,-.")
	fmt.Println("  |   |  |: |  '   ,'\\     |   | :                  |  | /\\/             :  : ' :                               :  : '                    ,'_ /| :  : '                :  : ' :  '   ,'\\ ,' ,'/ /|")
	fmt.Println("  :   :  :  / /   /   |    |   | |     .--,         :  : :    ,--.--.  .;__,'  /             ,---.     ,--.--.  |  ' |      ,---.    .--. |  | : |  ' |     ,--.--.  .;__,'  /  /   /   |'  | |' |")
	fmt.Println("  :   |    ; .   ; ,. :  ,--.__| |   /_ ./|         :  | |-, /       \\ |  |   |             /     \\   /       \\ '  | |     /     \\ ,'_ /| :  . | '  | |    /       \\ |  |   |  .   ; ,. :|  |   ,'")
	fmt.Println("  |   :     \\'   | |: : /   ,'   |, ' , ' :         |  : :/|.--.  .-. |:__,'| :            /    / '  .--.  .-. ||  | :    /    / ' |  ' | |  . . |  | :   .--.  .-. |:__,'| :  '   | |: :'  :  /")
	fmt.Println("  |   |   . |'   | .; :.   '  /  /___/ \\: |         |  |  .' \\__\\/: . .  '  : |__         .    ' /    \\__\\/: . .'  : |__ .    ' /  |  | ' |  | | '  : |__  \\__\\/: . .  '  : |__'   | .; :|  | '")
	fmt.Println("  '   :  '; ||   :    |'   ; |:  |.  \\  ' |         '  : '   ,\" .--.; |  |  | '.'|        '   ; :__   ,\" .--.; ||  | '.'|'   ; :__ :  | : ;  ; | |  | '.'| ,\" .--.; |  |  | '.'|   :    |;  : |")
	fmt.Println("  |   |  | ;  \\   \\  / |   | '/  ' \\  ;   :         |  | |  /  /  ,.  |  ;  :    ;        '   | '.'| /  /  ,.  |;  :    ;'   | '.'|'  :  `--'   \\;  :    ;/  /  ,.  |  ;  :    ;\\   \\  / |  , ;")
	fmt.Println("  |   :   /    `----'  |   :    :|  \\  \\  ;         |  : \\ ;  :   .'   \\ |  ,   /         |   :    :;  :   .'   \\  ,   / |   :    ::  ,      .-./|  ,   /;  :   .'   \\ |  ,   /  `----'   ---'")
	fmt.Println("  |   | ,'              \\   \\  /     :  \\  \\        |  |,' |  ,     .-./  ---`-'           \\   \\  / |  ,     .-./---`-'   \\   \\  /  `--`----'     ---`-' |  ,     .-./  ---`-'")
	fmt.Println("  `----'                 `----'       \\  ' ;        `--'    `--`---'                        `----'   `--`---'              `----'                         `--`---'")
	fmt.Println("体脂计算器")
	var err error
	var h string
	var w string
	var age string
	var sex string
	var ex = false
	var boody Boody
	for {
		fmt.Println("输入身高,输入exit退出计算器")
		fmt.Scan(&h)
		if strings.Contains(h, "exit") {
			ex = true
			break
		}
		boody.h, err = strconv.ParseFloat(h, 64)
		if err != nil {
			fmt.Println("请输入正确的值")
			continue
		}
		break
	}
	if ex {
		boody.err = errors.New("exit")
		return boody
	}
	for {
		fmt.Println("输入体重,输入exit退出计算器")
		fmt.Scan(&w)
		if strings.Contains(w, "exit") {
			ex = true
			break
		}
		boody.w, err = strconv.ParseFloat(w, 64)
		if err != nil {
			fmt.Println("请输入正确的值")
			continue
		}
		break
	}
	if ex {
		boody.err = errors.New("exit")
		return boody
	}
	for {
		fmt.Println("输入年龄,输入exit退出计算器")
		fmt.Scan(&age)
		if strings.Contains(age, "exit") {
			ex = true
			break
		}
		boody.age, err = strconv.ParseFloat(age, 64)
		if err != nil {
			fmt.Println("请输入正确的值")
			continue
		}
		break
	}
	if ex {
		boody.err = errors.New("exit")
		return boody
	}
	for {
		fmt.Println("输入性别,输入exit退出计算器")
		fmt.Scan(&sex)
		if strings.Contains(sex, "exit") {
			ex = true
			break
		}

		switch sex {
		case "男":
			boody.sex = 1
			break
		case "女":
			boody.sex = 0
			break
		case "1":
			boody.sex, err = strconv.ParseFloat(sex, 64)
			break
		case "0":
			boody.sex, err = strconv.ParseFloat(sex, 64)
			break
		}
		if err != nil {
			fmt.Println("请输入正确的值")
			continue
		}
		break
	}
	if ex {
		boody.err = errors.New("exit")
		return boody
	}

	boody = GetBMIOfBoody(boody)
	return boody
}

//体脂率计算
func GetBMIOfBoody(boody Boody) Boody {
	boody.BMI = boody.w * math.Pow(boody.h, 2)
	boody.BFR = 1.2*boody.BMI + 0.23*boody.age - 5.4 - 10.8*boody.sex

	switch boody.sex {
	case float64(1):
		switch true {
		case (boody.BFR < 2.0):
			boody.pro = "瘦"
			break
		case (2.0 <= boody.BFR && boody.BFR < 8.5):
			boody.pro = "偏瘦"
			break
		case (boody.BFR >= 8.5 && boody.BFR < 15.7):
			boody.pro = "理想"
			break
		case (boody.BFR >= 15.7 && boody.BFR < 26.0):
			boody.pro = "偏胖"
			break
		default:
			boody.pro = "胖"
			break
		}
		break
	case float64(0):
		switch true {
		case (boody.BFR < 11.3):
			boody.pro = "瘦"
			break
		case (11.3 <= boody.BFR && boody.BFR < 15.7):
			boody.pro = "偏瘦"
			break
		case (boody.BFR >= 15.7 && boody.BFR < 25.1):
			boody.pro = "理想"
			break
		case (boody.BFR >= 25.1 && boody.BFR < 31.3):
			boody.pro = "偏胖"
			break
		default:
			boody.pro = "胖"
			break
		}
		break
	}
	return boody
}

//作业05_封装一个函数，功能为交换两个1数字s
func swap(a interface{}, b interface{}) {
	a, b = b, a
}

//字符串交换参数
func swapbystring(a string, b string) {
	var as = &a
	var bs = &b
	var temp string
	temp = *as
	*as = *bs
	*bs = temp
}

//数字交换参数
func swapbyint(a int, b int) {
	var as = &a
	var bs = &b
	var temp int
	temp = *as
	*as = *bs
	*bs = temp
}

//浮点数交换参数
func swapbyfloat64(a float64, b float64) {
	var as = &a
	var bs = &b
	var temp float64
	temp = *as
	*as = *bs
	*bs = temp
}

//作业06_实现一个订票系统

//票总数
var picNum = 10

func DingPaoStart() {
	for {
		DingPao()
		if checkPic(1) {
			fmt.Printf("===================================目前系统余票:%d======================================", picNum)
			fmt.Println("")
			SystemStart()
		} else {
			fmt.Printf("===================================目前系统余票为%d,无法继续使用====================================", picNum)
			fmt.Println("")
			break
		}
	}
}

func DingPao() {
	fmt.Println("                                    _   _                             _")
	fmt.Println("                                   | | (_)                           | |")
	fmt.Println(" _ __ ___  ___  ___ _ ____   ____ _| |_ _  ___  _ __    ___ _   _ ___| |_ ___ _ __ ___")
	fmt.Println("| '__/ _ \\/ __|/ _ \\ '__\\ \\ / / _` | __| |/ _ \\| '_ \\  / __| | | / __| __/ _ \\ '_ ` _ \\")
	fmt.Println("| | |  __/\\__ \\  __/ |   \\ V / (_| | |_| | (_) | | | | \\__ \\ |_| \\__ \\ ||  __/ | | | | |")
	fmt.Println("|_|  \\___||___/\\___|_|    \\_/ \\__,_|\\__|_|\\___/|_| |_| |___/\\__, |___/\\__\\___|_| |_| |_|")
	fmt.Println("                                                             __/ |")
	fmt.Println("                                                            |___/")
	fmt.Println("==================================欢迎使用订票系统======================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
	fmt.Println("========================================================================================")
}

//定义个人信息结构体
type User struct {
	name      string
	number    string
	picNumber int
}

var users []User

//工具结构体
type Utel struct {
	hintarr []string
	ex      bool
	errstrs []string
}

func getUtel() Utel {
	var res Utel
	res.ex = false
	res.errstrs = []string{"请输入正确的值", "余票不足，出票失败", "出票成功"}
	var arr = []string{"输入姓名,输入exit重新输入信息", "输入身份证明,输入exit重新输入信息", "需要购买的票数,输入exit重新输入信息"}
	res.hintarr = arr
	return res
}

func SystemStart() {
	var fmtarr = make([]string, 3)
	var user User
	var utel = getUtel()
	var err error
	for i := 0; i < len(utel.hintarr); i++ {
		fmt.Println(utel.hintarr[i])
		fmt.Scan(&fmtarr[i])
		if strings.Contains(fmtarr[i], "exit") {
			utel.ex = true
			break
		}
		if i == 2 {
			user.name = fmtarr[0]
			user.number = fmtarr[1]
			user.picNumber, err = strconv.Atoi(fmtarr[2])
			if err == nil {
				if checkPic(user.picNumber) {
					fmt.Println(utel.errstrs[2])
					picNum -= user.picNumber
					users = append(users, user)
					break
				}
				fmt.Println(utel.errstrs[1])
			} else {
				fmt.Println(utel.errstrs[0])
			}
			i--
		}
	}
}

func checkPic(num int) bool {
	var ishave = false
	if picNum >= num {
		ishave = true
	}
	return ishave
}
